import logging
from logging.handlers import TimedRotatingFileHandler
import os
import threading


class Log:
    _instance_lock = threading.Lock()
    __first_init = False

    def __new__(cls, *args, **kwargs):
        if not hasattr(Log, "_instance"):
            with Log._instance_lock:
                if not hasattr(Log, "_instance"):
                    Log._instance = object.__new__(cls)
        return Log._instance

    def __init__(self):
        if not self.__first_init:
            # 第一步，创建一个logger
            self.logger = logging.getLogger()
            self.logger.setLevel(logging.INFO)
            # 第二步，创建一个handler，用于写入日志文件
            # filename：日志文件名的prefix；
            # when：是一个字符串，用于描述滚动周期的基本单位，字符串的值及意义如下：
            # “S”: Seconds
            # “M”: Minutes
            # “H”: Hours
            # “D”: Days
            # “W”: Week day (0=Monday)
            # “midnight”: Roll over at midnight
            # interval: 滚动周期，单位有when指定，比如：when=’D’,interval=1，表示每天产生一个日志文件
            # backupCount: 表示日志文件的保留个数
            base_dir = os.path.dirname(__file__)
            filepath = os.path.join(base_dir, "logs")
            os.makedirs(filepath, exist_ok=True)
            filename = os.path.join(filepath, f"log_backend_{os.getppid()}_{os.getpid()}.log")
            log_file_handler = TimedRotatingFileHandler(filename=filename, when="M", interval=2, backupCount=2)
            log_file_handler.setLevel(logging.DEBUG)
            # 创建一个handler，用于输出到控制台
            ch = logging.StreamHandler()
            ch.setLevel(logging.WARNING)
            # 第三步，定义handler的输出格式
            # %(levelno)s: 打印日志级别的数值
            # %(levelname)s: 打印日志级别名称
            # %(pathname)s: 打印当前执行程序的路径，其实就是sys.argv[0]
            # %(filename)s: 打印当前执行程序名
            # %(funcName)s: 打印日志的当前函数
            # %(lineno)d: 打印日志的当前行号
            # %(asctime)s: 打印日志的时间
            # %(thread)d: 打印线程ID
            # %(threadName)s: 打印线程名称
            # %(process)d: 打印进程ID
            # %(message)s: 打印日志信息
            formatter = logging.Formatter(
                "%(asctime)s - pid:%(process)d %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
            log_file_handler.setFormatter(formatter)
            ch.setFormatter(formatter)
            # 第四步，将logger添加到handler里面
            self.logger.addHandler(log_file_handler)
            self.logger.addHandler(ch)
            Log.__first_init = True
